home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 1 (Walnut Creek)
/
Aminet - June 1993 [Walnut Creek].iso
/
aminet
/
util
/
pack
/
ppcompress095.lha
/
ppcompress.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-11-14
|
8KB
|
354 lines
#include <exec/types.h>
#include <exec/memory.h>
#include <dos/dos.h>
#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
/* if you define NO_PRAGMAS before including proto/powerpacker.h */
/* you must link with ppSCglue.o or ppLCglue.o */
#include <proto/powerpacker.h>
#include <libraries/ppbase.h>
#include "ppcompress.h"
struct PPBase *PPBase = NULL; /* Home of PP */
APTR ci = NULL; /* PP's CrunchInfo array */
char *myname; /* program name, for operation diagnostic */
BPTR fp; /* global filehandle */
char *fn; /* global filename ptr for user messages */
UBYTE *data = NULL; /* PP's data buffer */
ULONG datalen; /* length of PP's data buffer */
BOOL enforce = 1; /* whether to enforce '.pp' extensions */
char ppsuff[] = ".pp"; /* filename extension (not?) to enforce */
char userbreak[] = "User break"; /* what to say when user kills me */
struct FileInfoBlock *fib;
int filesdone = 0;
/* prototypes */
void main(int, char **);
void process(char *, ULONG, ULONG, int);
char *tagname(char *, char *);
char *untagname(char *, char *);
BOOL uncrunch(char *, int);
BOOL crunch(char *, ULONG, ULONG, int);
void Usage(void);
BOOL __stdargs __saveds chkbrk(ULONG, ULONG, ULONG, APTR);
void clean(int, unsigned char);
extern char *GetMyStdIn(char *);
extern BOOL PutMyStdOut(UBYTE *, int);
char version[]="$VER: PPCompress/PPUnCompress/PPCat 0.95 (14.11.92)";
void main(int ac, char **av) {
char option;
ULONG eff=CRUN_VERYGOOD, speedup=SPEEDUP_BUFFMEDIUM;
char *optarg;
int i;
char tmpbuf[L_tmpnam+1];
if ( ac == 0 ) clean(20, QUIT);
fn=myname=av[0];
shift;
if ( !(PPBase = (struct PPBase *)OpenLibrary ("powerpacker.library", 35L)) ) {
fail("You need powerpacker.library V35+");
clean(20, QUIT);
}
while ( ac ) {
if (USER_HIT_CTRL_C) {
info(userbreak);
clean(10, QUIT);
}
if ( av[0][0] == '-' ) {
option = av[0][1];
if ( strlen(av[0]) == 2 ) {
shift;
optarg=av[0];
}
else optarg=&av[0][2];
switch ( option ) {
case 'h':
Usage();
clean(NULL, QUIT);
break;
case 'p':
i = atoi(optarg);
if ( (i != 0) && (i != 1) ) {
fail("-p must signal 0 or 1");
clean(10, QUIT);
}
else enforce = i;
break;
case 'e':
switch ( optarg[0] ) {
case 'f':
eff=CRUN_FAST;
break;
case 'm':
eff=CRUN_MEDIOCRE;
break;
case 'g':
eff=CRUN_GOOD;
break;
case 'v':
eff=CRUN_VERYGOOD;
break;
case 'b':
eff=CRUN_BEST;
break;
default:
fail("Unknown efficiency");
clean(10, QUIT);
break;
}
break;
case 'b':
switch ( optarg[0] ) {
case 's':
speedup=SPEEDUP_BUFFSMALL;
break;
case 'm':
speedup=SPEEDUP_BUFFMEDIUM;
break;
case 'l':
speedup=SPEEDUP_BUFFLARGE;
break;
default:
fail("Unknown speedup");
clean(10, QUIT);
break;
}
break;
}
shift;
}
else {
process(av[0], eff, speedup, FILE);
shift;
filesdone++;
}
}
if ( !filesdone ) process(GetMyStdIn(tmpbuf), eff, speedup, PIPE);
DeleteFile(tmpbuf);
clean(0, QUIT);
}
void process(char *file, ULONG eff, ULONG speedup, int mode) {
fn = file;
if ( !strcmp(myname, "ppcompress") ) crunch(file, eff, speedup, mode);
else if ( !strcmp(myname, "ppuncompress") ) uncrunch(file, mode);
else if ( !strcmp(myname, "ppcat") ) uncrunch(file, PIPE);
else {
fail("Must be ppcompress, ppuncompress, or ppcat");
clean(10, QUIT);
}
return;
}
char *tagname(char *in, char *out) {
if ( !enforce ) strncpy(out, in, 30); /* if no ext enforcing, don't tag */
else {
strncpy(out, in, 27);
strcat (out, ppsuff);
}
return (out);
}
char *untagname(char *in, char *out) {
char *p;
BPTR tmpfp;
strncpy(out, in, 30);
if ( p=strrchr(out, '.') ) {
if ( !strcmp(p, ppsuff) ) *p='\0';
if ( !(tmpfp = Open(in, MODE_OLDFILE)) ) {
p = &in[(strlen(in)>27?27:strlen(in))];
strcpy (p, ppsuff);
}
else Close(tmpfp);
}
return(in);
}
BOOL uncrunch(char *in_fn, int mode) {
int err;
char in_fn2[31];
char out_fn[31];
strncpy(in_fn2, in_fn, 30);
in_fn = untagname(in_fn2, out_fn);
err = ppLoadData(in_fn, DECR_NONE, MEMF_PUBLIC, &data, &datalen, NULL);
if ( err ) {
fail(ppErrorMessage(err));
return(FALSE);
}
if ( mode == FILE ) {
fn=out_fn;
if ( !(fp=(BPTR)Open(out_fn, MODE_NEWFILE)) ) {
fail("Could not create file");
clean(20, FREEMEM);
return(FALSE);
}
if ( Write(fp, data, datalen) != datalen ) {
fail("Could not write whole file");
clean(20, CLOSEFP | FREEMEM);
return(FALSE);
}
clean(0, CLOSEFP | FREEMEM);
if ( strcmp(in_fn, out_fn) ) {
if ( !(DeleteFile(in_fn)) ) {
fn=in_fn;
fail("Could not delete file");
}
}
}
else {
BOOL stat;
stat=PutMyStdOut(data, datalen);
clean(0, FREEMEM);
if ( !stat ) {
Write(Output(), "\n", 1);
return(FALSE);
}
}
return(TRUE);
}
BOOL crunch(char *in_fn, ULONG eff, ULONG speedup, int mode) {
ULONG crunchlen;
char out_fn[31];
BPTR lock;
if ( !(ci = ppAllocCrunchInfo(eff, speedup, chkbrk, NULL)) ) {
fail("Can't allocate crunch space");
clean(20, QUIT);
}
if ( (fp=(BPTR)Open(in_fn, MODE_OLDFILE)) == NULL ) {
fail("Could not open file");
clean(0, FREECI);
return(FALSE);
}
if ( !(fib = AllocMem(sizeof(struct FileInfoBlock), MEMF_PUBLIC)) ) {
fail("Could not get data size");
clean(20, FREECI);
}
if ( !(lock = Lock(in_fn, ACCESS_READ)) ) {
fail("Could not lock file");
clean(0, CLOSEFP | FREECI | FREEFIB);
return(FALSE);
}
if ( !(Examine(lock, fib)) ) {
fail("Could not stat file");
UnLock(lock);
clean(0, CLOSEFP | FREECI | FREEFIB);
return(FALSE);
}
UnLock(lock);
if ( fib->fib_DirEntryType > 0 ) {
clean(0, CLOSEFP | FREECI | FREEFIB);
return(FALSE); /* ignore any dirs in list */
}
datalen=fib->fib_Size;
FreeMem(fib, sizeof(struct FileInfoBlock));
if ( !(data=AllocMem(datalen, MEMF_PUBLIC)) ) {
fail("Could not allocate a crunch buffer");
clean(0, CLOSEFP | FREECI);
return(FALSE);
}
if ( Read(fp, data, datalen) != datalen ) {
fail("Could not read whole file");
clean(0, CLOSEFP | FREEMEM | FREECI);
return(FALSE);
}
switch ( crunchlen=ppCrunchBuffer(ci, data, datalen) ) {
case PP_CRUNCHABORTED:
info(userbreak);
clean(0, CLOSEFP | FREEMEM | FREECI);
return(FALSE);
case PP_BUFFEROVERFLOW:
fail("Buffer overflow; no compression possible");
clean(0, CLOSEFP | FREEMEM | FREECI);
return(FALSE);
default:
clean(0, CLOSEFP | FREECI);
}
if ( mode == FILE ) {
tagname(in_fn, out_fn);
fn=out_fn;
if ( !(fp=(BPTR)Open(out_fn, MODE_NEWFILE)) ) {
fail("Could not create file");
clean(20, FREEMEM);
return(FALSE);
}
if ( !(ppWriteDataHeader(fp, eff, FALSE, NULL)) ) {
fail("Could not write PP header");
clean(20, CLOSEFP | FREEMEM);
return(FALSE);
}
if ( Write(fp, data, crunchlen) != crunchlen ) {
fail("Could not write whole file");
clean(20, CLOSEFP | FREEMEM);
return(FALSE);
}
clean(0, CLOSEFP | FREEMEM);
if ( enforce ) {
if ( !(DeleteFile(in_fn)) ) {
fn=in_fn;
fail("Could not delete file");
}
}
}
else {
BOOL stat;
if ( !(ppWriteDataHeader(Output(), eff, NULL, NULL)) ) {
fail("Could not write PP header");
clean(20, FREEMEM);
return(FALSE);
}
stat=PutMyStdOut(data, crunchlen);
clean(0, FREEMEM);
if ( !stat ) return(FALSE);
}
return(TRUE);
}
void Usage(void) {
fprintf(stderr, "%s: Usage:\n%s [-p 0|1] [-e f|m|g|v|b] [-b s|m|l] file [file [...] ]\n",myname, myname);
return;
}
/* callback func for ppcruncher; check for user break */
BOOL __stdargs __saveds chkbrk(ULONG lensofar, ULONG crunlen, ULONG totlen, APTR userdata) {
if (USER_HIT_CTRL_C) return(FALSE);
else return(TRUE);
}
/* use this to free global allocations or to quit */
void clean(int code, unsigned char flags) {
/* free all resources */
if (flags & FREEFIB) FreeMem(fib, sizeof(struct FileInfoBlock));
if (flags & FREECI) ppFreeCrunchInfo(ci);
if (flags & FREEMEM) FreeMem (data, datalen);
if (flags & CLOSEFP) Close(fp);
if (flags & QUIT) {
if (PPBase) CloseLibrary ((struct Library *)PPBase);
exit (code);
}
else return;
}